home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Collections: Panorama
/
Panorama - Disk 19D (1987-07-22)(Pacific North-West Amigas Club)[WB].zip
/
Panorama - Disk 19D (1987-07-22)(Pacific North-West Amigas Club)[WB].adf
/
WarpText2.0
/
WarpText.asm
< prev
next >
Wrap
Assembly Source File
|
1987-07-19
|
22KB
|
547 lines
* --------------------------------------------------------------------------
* WarpText.asm Version 2.0 Bill Kelly
* 07/07/87
*
* Copyright 1987 by Bill W. Kelly.
*
XDEF InitWarpInfo
XDEF GotoXY
XDEF GetXY
XDEF WarpText
XDEF SetupFont
XDEF NewWarp
XDEF XORCursor
NOLIST ; I don't want to see all of this junque...
INCLUDE "graphics/text.i"
INCLUDE "graphics/gfx.i"
INCLUDE "graphics/WarpText.i"
LIST ; Turn listing back on...
CODE ; WarpText begins...
* ==========================================================================
*
* | __ ___ __ __ |
* | / \ / / \ / / /| / \ / \ |
* \|/ / / / / / / / / /_| /\__/ /\__/ \|/
* V \__/ /___ /___/ \/\/ / | / \ / V
*
* --------------------------------------------------------------------------
* InitWarpInfo:
* -------------
*
* INITWARPINFO NEEDS:
*
* a0 - Pointer to an instance of the WarpInfo structure, with the following
* fields initialized:
*
* wi_TextFont: Pointer to an open font. (I.e. what OpenFont() returns
* to you, other than NULL.)
* wi_BitMap: Pointer to an initialized, 'working' BitMap structure.
* (E.g. Open a window. Get the pointer to the screen
* out of wd_WScreen. From there the BitMap structure is
* at sc_BitMap, which is an offset, not a pointer, into
* the Screen structure.)
* wi_WhichPlane: Which bitplane you want the routine to draw into.
* Numbering begins at zero. On the Workbench screen
* (or any two-bitplane screen) the possible numbers for
* wi_WhichPlane are 0 and 1.
* wi_Left: Left edge of the 'window' (in character locations)
* you want the routine to write into.
* wi_Top: Top edge of the 'window' in character locations.
* wi_Width: Width of 'window' (also on character locations).
* wi_Height: Height of 'window' -- guess what? Character locations.
*
* REGISTER USAGE FOR INITWARPINFO:
*
* d0 - Left, Top, Width, Height, etc.
* d1 - wi_Modulo
* d2 - Scratch
* d3 - Y size of font
* d4 - Scratch
*
* a0 - Pointer to WarpInfo structure with above fields initialized.
* a1 - Addr of top of bitplane, wi_WindowTop, etc.
* a2 - Scratch
*
InitWarpInfo: movem.l d0-d4/a1-a2,-(sp)
moveq #0,d4 ; Clear scratch.
move.w d4,wi_CurX(a0) ; Store it in WarpInfo.
move.w wi_Width(a0),wi_LastX(a0) ; Max X position.
sub.w #1,wi_LastX(a0) ; make it 0-relative.
move.l wi_BitMap(a0),a1 ; Get some stuff from bmap.
moveq #0,d2
move.w bm_BytesPerRow(a1),d2 ; #bytes per row in d2
move.w d2,wi_BPMod(a0) ; #bytes per row->wi_BPMod
move.w wi_WhichPlane(a0),d4 ; Get bitplane#.
asl.l #2,d4 ; Multiply plane# by four.
move.l bm_Planes(a1,d4.l),a1 ; Get address of bitplane.
moveq #0,d3
move.l wi_TextFont(a0),a2
move.w tf_YSize(a2),d3 ; Get YSize of font.
moveq #0,d1
move.l d2,d1 ; Copy bytesperrow to d1.
mulu.w d3,d1 ; YSize*BytesPerRow.
move.w d1,wi_Modulo(a0) ; Store it in WarpInfo.
moveq #0,d4
move.l d1,d4 ; Copy wi_modulo to scratch.
mulu.w wi_Top(a0),d4 ; Mul by Y offset.
add.w wi_Left(a0),d4 ; Add X offset.
move.l a1,a2 ; BPlane addr to scratch.
add.l d4,a2 ; Add offset to btpln addr.
move.l a2,wi_WindowTop(a0) ; Stick in WarpInfo.
move.l a2,wi_CurLine(a0) ; Stick in WarpInfo.
moveq #0,d2
move.w wi_Top(a0),d2 ; Copy Y top to scratch.
add.w wi_Height(a0),d2 ; Add Y height to Y top.
move.l d1,d4 ; Copy wi_modulo to scratch.
mulu.w d2,d4 ; Mul by Y offset.
add.w wi_Left(a0),d4 ; Add X offset.
move.l a1,a2 ; BPlane addr to scratch.
add.l d4,a2 ; Add offset to btpln addr.
move.l a2,wi_LastLine(a0) ; Stick in WarpInfo.
movem.l (sp)+,d0-d4/a1-a2
rts
*
* --------------------------------------------------------------------------
* --------------------------------------------------------------------------
* GotoXY:
* -------
*
* GOTOXY NEEDS:
*
* d0 - New X position. \ All regs. but d1 preserved,
* d1 - New Y position.
*
* a0 - Pointer to initialized WarpInfo structure.
*
* NOTE: These positions are given in character locations, like everything
* else... The positions are relative to the 'window' you have
* defined using InitWarpInfo. Position 0,0 is the character in the
* top left corner of the window.
* This routine does no error checking. (You're supposed to know
* how big your window is...)
*
GotoXY: move.w d0,wi_CurX(a0) ; Set new X position.
mulu.w wi_Modulo(a0),d1 ; Make Y an offset into window
add.l wi_WindowTop(a0),d1 ; Add this offset to the window
move.l d1,wi_CurLine(a0) ; to make it the new Y position.
rts
*
* --------------------------------------------------------------------------
* --------------------------------------------------------------------------
* GetXY:
* ------
*
* GETXY NEEDS:
*
* a0 - Pointer to an initialized WarpInfo structure.
*
* It returns the current X position in d0 and the current Y
* position in d1.
*
GetXY: move.l wi_CurLine(a0),d1 ; Get current Y addr
sub.l wi_WindowTop(a0),d1 ; Sub window to get Y offset.
divu.w wi_Modulo(a0),d1 ; Should not be a remainder.
moveq #0,d0
move.w wi_CurX(a0),d0 ; Get current X position.
rts
*
* --------------------------------------------------------------------------
* --------------------------------------------------------------------------
* WarpText:
* ---------
*
* WARPTEXT NEEDS:
*
* d0 - Number of characters to type. (count)
*
* a0 - Pointer to an initialized WarpInfo structure. (See InitWarpInfo)
* a1 - Address of string of characters to type.
*
* REGISTER USAGE FOR WARPTEXT: (All regs preserved but d0 which will be 0)
*
* d0 - Number of characters to type (count)
* d1 - Character to be emitted
* d2 - LoChar
* d3 - HiChar
* d4 - Current X position
* d5 - Scratch
* d7 - Bitplane modulo: add to get to next raster line in bitplane.
*
* a0 - Pointer to WarpInfo structure
* a1 - Address of string of characters to type
* a2 - Pointer to TextFont structure, address of tf_CharData
* a3 - Addr of Current line.
* a4 - Scratch
* a5 - Scratch
*
* STACK USAGE FOR WARPTEXT:
*
* 0(sp) - Last line
* 4(sp) - Top line
* 8(sp) - tf_YSize
* 12(sp) - tf_Modulo: add it to get to next line in font data
* 16(sp) - wi_Modulo: add it to get to next line in bitplane 'window'
* 20(sp) - Maximum (last) possible X position on a line
*
sp_LastLine: equ 0 ; Offsets into stack to get at this data.
sp_TopLine: equ 4
sp_YSize: equ 8
sp_tf_Mod: equ 12
sp_wi_Mod: equ 16
sp_LastX: equ 20
NoChar: equ 256 ; I thought this was where the "empty-box"
; character was. It isn't. Anyone know where
; it is? Or am I supposed to generate it
; myself????
WarpText: movem.l d1-d5/d7/a2-a5,-(sp)
moveq #0,d4
move.w wi_CurX(a0),d4 ; Get current X position.
moveq #0,d5
move.w wi_LastX(a0),d5 ; Get maximum X position.
move.l d5,-(sp) ; Stick it on stack. (1st item)
move.w wi_Modulo(a0),d5 ; Get wi_Modulo.
move.l d5,-(sp) ; Stick it on stack. (2nd item)
move.l wi_TextFont(a0),a2 ; Use TextFont to get some stuff:
moveq #0,d2
move.b tf_LoChar(a2),d2 ; Get tf_LoChar.
moveq #0,d3
move.b tf_HiChar(a2),d3 ; Get tf_HiChar.
move.w tf_Modulo(a2),d5 ; Get tf_Modulo.
move.l d5,-(sp) ; Stick it on stack. (3rd item)
move.w tf_YSize(a2),d5 ; Get tf_YSize
move.l d5,-(sp) ; Stick it on stack. (4th item)
move.l tf_CharData(a2),a2 ; Replace textfont w/ tf_Chardata.
move.l wi_WindowTop(a0),a4 ; Get addr of wi_WindowTop.
move.l a4,-(sp) ; Stick it on stack. (5th item)
move.l wi_LastLine(a0),a4 ; Get addr of wi_LastLine.
move.l a4,-(sp) ; Stick it on stack. (6th item)
move.l wi_CurLine(a0),a3 ; Get addr of wi_CurLine.
moveq #0,d7
move.w wi_BPMod(a0),d7 ; Get wi_BPMod.
subq #1,d0 ; Take one from count.
moveq #0,d1 ; Clear d1 because using .b size.
subq #1,d4 ; Take one from Current X.
DoNextChar: addq #1,d4 ; Add 1 to Current X.
DoNextSinAdd: move.b (a1)+,d1 ; Move char to emit to d1.
cmpi.b #32,d1 ; Is it a space?
beq Blank
cmp.b d2,d1 ; Compare with LoChar.
blt BoffoChar ; May be a LF, FF, CR, etc.
cmp.b d3,d1 ; Compare with HiChar.
blt DoNoChar
move.l a2,a4 ; Copy tf_CharData to scratch.
sub.l d2,d1 ; Sub LoChar from char.
adda.l d1,a4 ; Add char to tf_CharData.
DoChar: move.l a3,a5 ; Copy current line to scratch.
adda.l d4,a5 ; Add XPos to current line.
move.l sp_YSize(sp),d5 ; YSize is loop count.
subq.l #1,d5
MoveChar: move.b (a4),(a5) ; Move line of char to bitplane.
adda.l sp_tf_Mod(sp),a4 ; Add tf_Modulo to tf_Chardata.
adda.l d7,a5 ; Add wi_BPMod to bitplane.
dbra d5,MoveChar
Blank: cmp.l sp_LastX(sp),d4 ; Compare max X and Current X...
blt GotoDoNext ; Do next if current < max.
DoLF: moveq #0,d4 ; Xpos is zero now.
DoCR: cmpa.l (sp),a3 ; CMP sp_LastLine with current.
beq GotoNSA ; Wrap on line if equ.
adda.l sp_wi_Mod(sp),a3 ; Point at next line.
bra GotoNSA ; Do another character.
DoNoChar: move.l a2,a4 ; Copy tf_Chardata to scratch.
add.l #NoChar,a4 ; Point at empty-box char.
bra DoChar ; Do the empty-box char.
BoffoChar: cmpi.l #10,d1 ; Is is a linefeed?
beq DoLF
cmpi.l #12,d1 ; Is it a formfeed?
beq DoFF
cmpi.l #13,d1 ; Is it a CR?
beq DoCR
bra DoNoChar ; Fine. Put up the box.
DoFF: moveq #0,d4 ; Make X pos zero. | It doesn't
move.l sp_TopLine(sp),a3 ; Point at top | CLS yet.
bra GotoNSA
GotoDoNext: dbra d0,DoNextChar ; Keep looping?
bra WindUp ; Loop is done. Clean up & bail.
GotoNSA: dbra d0,DoNextSinAdd ; Do NextChar without adding.
WindUp: addq.l #8,sp ; Get rid of stuff kept on stack.
addq.l #8,sp
addq.l #8,sp
move.w d4,wi_CurX(a0) ; Store current X for next time.
move.l a3,wi_CurLine(a0) ; Store current Y for next time.
movem.l (sp)+,d1-d5/d7/a2-a5
rts
*
* ==========================================================================
* ==========================================================================
*
* | ___ __ __ |
* | /| / / / / / / /| / \ / \ |
* \|/ / | / /--- / / / / / / /_| /\__/ /\__/ \|/
* V / |/ /___ \/\/ \/\/ / | / \ / V
*
* --------------------------------------------------------------------------
* SetupFont:
* ----------
* Call with NewWarpInfo and TextFont on the stack.
* (TextFont should be on top)
*
* You must allocate a 2048 byte buffer (does not have to reside in CHIP RAM)
* and store its address into the nwi_FontData field of the NewWarpInfo
* structure prior to calling SetupFont.
* SetupFont will take the font data from the pointer to the FontData
* structure you supply on the stack and rearrange it into the 2048 byte
* array. It is not a smart routine -- it is set up to unpack only the
* Topaz 8 font, or any 8x8 font with the same number of characters as topaz
* and the same modulo. If you want to use an 8x8 font that has different
* number of characters defined and a different modulo, you will have to
* modify the SetupFont code.
*
SetupFont: movem.l d0/a0-a3,-(sp) ;Save used regs
move.l 24(sp),a2 ;FontData kept in a2
move.l 28(sp),a1 ;NewWarpInfo kept in a1
move.l nwi_FontData(a1),a0 ;array to rearrange font into
move.l #31,d0 ;number of blank chars.
TheUnCola: move.b #$FE,(a0)+ ;$FE = %11111110
move.b #$C6,(a0)+ ;$C6 = %11000110
move.b #$C6,(a0)+ ;$C6 = %11000110
move.b #$C6,(a0)+ ;$C6 = %11000110
move.b #$C6,(a0)+ ;$C6 = %11000110
move.b #$C6,(a0)+ ;$C6 = %11000110
move.b #$FE,(a0)+ ;$FE = %11111110
move.b #$00,(a0)+ ;$00 = %00000000
dbf d0,TheUnCola ;Get the picture? :-)
move.l tf_CharData(a2),a2 ;get addr of the font data
move.l a2,a3 ;save for later loops
moveq #0,d0 ;zero is 1st char in chardata
DoAnother: add.w d0,a2 ;add char offset to chardata
move.b (a2),(a0)+ ;begin copying char into array
add.w #192,a2 ;add tf_modulo for next byte
move.b (a2),(a0)+
add.w #192,a2
move.b (a2),(a0)+
add.w #192,a2
move.b (a2),(a0)+
add.w #192,a2
move.b (a2),(a0)+
add.w #192,a2
move.b (a2),(a0)+
add.w #192,a2
move.b (a2),(a0)+
add.w #192,a2
move.b (a2),(a0)+ ;finished copying this character
move.l a3,a2 ;point to chardata again
addq.b #1,d0 ;add one for next character
cmp.w #223,d0 ;need to stop after 223rd char
ble.s DoAnother
movem.l (sp)+,d0/a0-a3 ;restore used regs
rts
*
* --------------------------------------------------------------------------
* --------------------------------------------------------------------------
* NewWarp:
* --------
* Call with NewWarpInfo, String-address, and String-count on the stack.
* (String-count should be on top)
*
* You must have called SetupFont AND have filled in the nwi_BitPlane
* field in the NewWarpInfo structure before you call NewWarp.
* It would be a good idea, also, to make sure you've set up nwi_XLoc
* and nwi_YLoc to the correct places before you go writing text.
* They are character-position relative, rather than pixel relative.
* Setting nwi_XLoc and nwi_XLoc to 8,8 for example, would be like telling
* the Graphics library Text() routine to write text at 80,80.
* Another note: Unlike Text(), NewWarp writes directly into a bitplane
* and does not do clipping at the edges of rastports. This makes
* NewWarp very fast, but less flexible. I have found it easiest to
* use the WarpText routines in SUPER_BITMAP windows.
*
NewWarp: movem.l d0-d3/a0-a4,-(sp) ;save used registers
move.l 40(sp),d3 ;String-count kept in d3
move.l 44(sp),a2 ;String-addr kept in a2
move.l 48(sp),a4 ;NewWarpInfo kept in a4
move.w nwi_XLoc(a4),d0 ;move to d0 before incrementing
add.w d3,nwi_XLoc(a4) ;increment XLoc like Text()
subq.w #1,d3 ;adjust count for dbf
move.w nwi_YLoc(a4),d1
move.l nwi_BitPlane(a4),a0
move.l nwi_FontData(a4),a1
move.l a1,a3 ;safe keeping of FontData
asl.w #7,d1 ;This multiplies YLoc
move.w d1,d2 ;times 640 in 26 cycles
asl.w #2,d1 ;instead of the 74 cycles
add.w d2,d1 ;a MULU would take.
add.w d0,d1 ;Add XLOC to expanded YLOC.
add.w d1,a0 ;Add LOC offset to bitplane.
OnceAgain: moveq #0,d0
move.b (a2)+,d0 ;Put character in d0.
asl.w #3,d0 ;Make offset into FontData
add.w d0,a1 ;Add offset to fontData address.
move.b (a1)+,(a0) ;Start moving the font data
add.w #80,a0 ;into the bitmap...
move.b (a1)+,(a0)
add.w #80,a0
move.b (a1)+,(a0)
add.w #80,a0
move.b (a1)+,(a0)
add.w #80,a0
move.b (a1)+,(a0)
add.w #80,a0
move.b (a1)+,(a0)
add.w #80,a0
move.b (a1)+,(a0)
add.w #80,a0
move.b (a1)+,(a0) ;Finished moving data.
sub.w #559,a0 ;restore a0 to next char loc
move.l a3,a1 ;restore a1 to FontData
dbf d3,OnceAgain
movem.l (sp)+,d0-d3/a0-a4 ;restore used registers
rts
*
* --------------------------------------------------------------------------
* --------------------------------------------------------------------------
* XORCursor:
* ----------
* Call with NewWarpInfo on the stack.
*
* You must have called SetupFont AND have filled in the nwi_BitPlane
* field in the NewWarpInfo structure before you call XORCursor.
* XORCursor XOR's a console-device-like cursor to the current xy location.
* To get the cursor to be a different color than the Text you've been
* emitting with NewWarp you have to change the bitplane being pointed to
* by nwi_BitPlane. I thought of adding another APTR to the end of
* the NewWarpInfo structure called nwi_CursorPlane that you could set
* to point to a different bitplane which would only be used only
* by XORCursor. I haven't yet, as I want to get this stuff out.
* If you would like to, feel free to do so.
*
XORCursor: movem.l d0-d1/a0-a1,-(sp) ;Save used registers
move.l 20(sp),a1 ;NewWarpInfo kept in a1
move.w nwi_YLoc(a1),d0
move.l nwi_BitPlane(a1),a0
asl.w #7,d0 ;This multiplies YLoc
move.w d0,d1 ;times 640 in 26 cycles
asl.w #2,d0 ;instead of the 74 cycles
add.w d1,d0 ;a MULU would take.
add.w nwi_XLoc(a1),d0 ;Add XLOC to expanded YLOC.
add.w d0,a0 ;Add LOC offset to bitplane.
eor.b #$FF,(a0) ;XOR the cursor...
add.w #80,a0
eor.b #$FF,(a0)
add.w #80,a0
eor.b #$FF,(a0)
add.w #80,a0
eor.b #$FF,(a0)
add.w #80,a0
eor.b #$FF,(a0)
add.w #80,a0
eor.b #$FF,(a0)
add.w #80,a0
eor.b #$FF,(a0)
add.w #80,a0
eor.b #$FF,(a0)
movem.l (sp)+,d0-d1/a0-a1 ;restore used registers
rts
*
* ==========================================================================
END ; WarpText ends.
* --------------------- *
* End of "WarpText.asm" *
* --------------------- *